home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / PASCAL / 0188.ZIP / ITRMPORT.INC < prev    next >
Text File  |  1985-02-20  |  11KB  |  294 lines

  1. Const
  2.      RECV_BUF_SIZE = 2048;             {this may be changed to
  3.                                         whatever size you need}
  4. { *** Port addresses *** }
  5.      THR = $3F8;                       {Transmitter Holding Register: the
  6.                                         serial port address we use to send
  7.                                         data}
  8.      IER = $3F9;                       {Interrupt Enable Register for the
  9.                                         serial port}
  10.      LCR = $3FB;                       {Line Control Register for the serial
  11.                                         port. Determines data bits, stop bits
  12.                                         and parity, contributes to setting
  13.                                         baud-rate}
  14.      MCR = $3FC;                       {Modem Control Register}
  15.      LSR = $3FD;                       {Line Status Register}
  16.      MSR = $3FE;                       {Modem Status Register}
  17.      IMR = $021;                       {Interrupt Mask Register port address
  18.                                         of Intel 8259A Programmable Interrupt
  19.                                         controller}
  20. { *** Masks *** }
  21.      ENABLE_OUT2 = 8;                  {Setting bit 3 of MCR enables OUT2}
  22.      ENABLE_DAV = 1;                   {Setting bit 0 of IER enables Data
  23.                                         AVailable interrupt from serial port}
  24.      ENABLE_IRQ4 = $EF;                {Clearing bit 5 of IMR enables serial
  25.                                         interrupts to reach the CPU}
  26.      DISABLE_OUT2 = 1;                 {Clearing MCR disables OUT2}
  27.      DISABLE_DAV = 0;                  {Clearing IER disables Data
  28.                                        AVailable interrupt from serial port}
  29.      DISABLE_IRQ4 = $10;               {Setting bit 5 of IMR stops serial
  30.                                         interrupts from reaching the CPU}
  31.      SET_BAUD = $80;                   {Setting bit 7 of LCR allows us to set
  32.                                         the baud rate of the serial port}
  33.      SET_PARMS = $7F;                  {Clearing bit 7 of LCR allows us to set
  34.                                         non-baud-rate parameters on the
  35.                                         serial port}
  36. Type
  37.     parity_set        = (none,even);    {readability and expansion}
  38. Var
  39.    buf_start, buf_end    : integer;    {NOTE: these will change by them-
  40.                                         selves in the background}
  41.    recv_buffer           : array [1..RECV_BUF_SIZE] of byte;
  42.                                        {also self-changing}
  43.    speed                 : integer;    {I don't know the top speed these
  44.                                         routines will handle}
  45.    dbits                 : 7..8;       {only ones most people use}
  46.    stop_bits             : 1..2;       {does anyone use 2?}
  47.    parity                : parity_set;  {even and none are the common ones}
  48.  
  49. function cgetc(TimeLimit : integer) : integer;
  50. {if a byte is recieved at COM1: in less than TimeLimit seconds,
  51.  returns byte as an integer, else returns -1}
  52. const
  53.      TIMED_OUT = -1;
  54. begin
  55.      TimeLimit := TimeLimit shl 10;     {convert TimeLimit to millisecs}
  56.      while (buf_start = buf_end) and (TimeLimit > 0) do
  57.      begin
  58.           delay(1);
  59.           TimeLimit := pred(TimeLimit)
  60.      end;
  61.      if (TimeLimit >= 0) and (buf_start <> buf_end) then
  62.      begin
  63.           inline ($FA);            {suspend interrupts}
  64.           cgetc := recv_buffer[buf_start];
  65.           buf_start := succ(buf_start);
  66.           if buf_start > RECV_BUF_SIZE then
  67.           buf_start := 1;
  68.           inline ($FB);            {resume interrupts}
  69.      end
  70.      else
  71.          cgetc := TIMED_OUT;
  72. end;
  73.  
  74. procedure send(c : byte);
  75. var
  76.    a : byte;
  77. begin
  78.   repeat
  79.        a := port[LSR]
  80.   until odd(a shr 5);
  81.   port[THR] := c;
  82. end;
  83.  
  84. procedure StrSend(s : bigstring);
  85. var
  86.    i : integer;
  87. begin
  88.      for i := 1 to length(s) do
  89.          send(ord(s[i]));
  90. end;
  91.  
  92. procedure SendPaced(s : bigstring);
  93. label
  94.      99;
  95. const
  96.      CRSYM = '<';
  97. var
  98.    i : integer;
  99.    c : integer;
  100. begin
  101.      for i := 1 to Length(s) do
  102.      begin
  103.           if s[i] = CRSYM then
  104.              send(13)
  105.           else
  106.              send(ord(s[i]));
  107.           c := cgetc(1);
  108.           if c <> -1 then
  109.              write(chr(c))
  110.           else begin
  111.              sound(440);
  112.              delay(20);
  113.              nosound;
  114.              goto 99
  115.           end
  116.      end;
  117. 99:
  118. end;
  119.  
  120. {Communications routines for TURBO Pascal written by Alan Bishop,
  121.  modified slightly by Scott Murphy.
  122.  Handles standart COM1: ports with interrupt handling.  Includes
  123.  support for only one port, and with no overflow, parity, or other
  124.  such checking.  However, even some of the best communication programs
  125.  don't do this anyway, and I never use it.  If you make modifications,
  126.  please send me a copy if you have a simple way of doing it (CIS EMAIL,
  127.  Usenet, MCI Mail, etc)  Hope these are useful.
  128.  
  129. Alan Bishop - CIS      - 72405,647
  130.               Usenet   - bishop@ecsvax
  131.               MCI Mail - ABISHOP
  132. }
  133. procedure update_uart;
  134. {uses dbits, stop_bits, and parity}
  135. var
  136.    newparm, oldLCR : byte;
  137. begin
  138.  newparm := dbits-5;
  139.  if stop_bits = 2 then newparm := newparm + 4;
  140.  if parity = even then newparm := newparm + 24;
  141.  oldLCR := port[LCR];
  142.  port[LCR] := oldLCR and SET_PARMS;
  143.  port[LCR] := newparm;
  144. end;
  145.  
  146.  
  147. procedure term_ready(state : boolean);
  148. {if state = TRUE then set RTS true else set false}
  149. var
  150.    OldMCR : byte;
  151. begin
  152.      OldMCR := port[MCR];
  153.      if state then
  154.         port[MCR] := OldMCR or 1
  155.      else
  156.          port[MCR] := OldMCR and $FE
  157. end;
  158.  
  159. function carrier : boolean;
  160. {true if carrier, false if not}
  161. begin
  162.  carrier := odd(port[MSR] shr 7);
  163. end;
  164.  
  165. procedure set_up_recv_buffer;
  166. begin
  167.  buf_start := 1;
  168.  buf_end   := 1;
  169. end;
  170.  
  171. procedure new_baud(rate : integer);
  172. {has no problems with non-standard bauds}
  173. var
  174.    OldLCR : byte;
  175. begin
  176.  if rate <= 9600 then
  177.  begin
  178.   speed := rate;
  179.   rate := trunc(115200.0/rate);
  180.   OldLCR := port[LCR] or SET_BAUD;
  181.   port[LCR] := OldLCR;
  182.   port[THR] := lo(rate);
  183.   port[IER] := hi(rate);
  184.   port[LCR] := OldLCR and SET_PARMS;
  185.  end;
  186. end;
  187.  
  188. procedure init_port;
  189. {installs interrupt sevice routine for serial port}
  190. var a,b : integer;
  191.     buf_len : integer;
  192. begin
  193.  update_uart;
  194.  new_baud(speed);
  195.  buf_len := RECV_BUF_SIZE;
  196.  
  197.  {this is the background routine}
  198.  
  199.  inline (
  200.               $1E/                     {push ds}
  201.               $0E/                     {push cs}
  202.               $1F/                     {pop  ds                  ;ds := cs}
  203.               $BA/*+23/                {mov  dx, offset ISR}
  204.               $B8/$0C/$25/             {mov  ax, 250CH           ;set COM1: vector}
  205.               $CD/$21/                 {int  21H}
  206.               $8B/$BE/BUF_LEN/         {mov  di, buf_len}
  207.               $89/$3E/*+87/            {mov  lcl_buf_len,di}
  208.               $1F/                     {pop  ds}
  209.               $2E/$8C/$1E/*+83/        {mov  lcl_ds, ds}
  210.               $EB/$51/                 {jmp  exit}
  211. {ISR:}        $FB/                     {sti}
  212.               $1E/                     {push ds}
  213.               $50/                     {push ax}
  214.               $53/                     {push bx}
  215.               $52/                     {push dx}
  216.               $56/                     {push si}
  217.               $2E/$8E/$1E/*+70/        {mov  ds,[lcl_ds]}
  218.               $BA/$F8/$03/             {mov  dx, 3F8H           ;address RBR}
  219.               $EC/                     {in   al, dx             ;read rbr}
  220.               $BE/RECV_BUFFER/         {mov  si, recv_buffer    ;address start of recv_buffer}
  221.               $8B/$1E/BUF_END/         {mov  bx, [buf_end]      ;index of current char in recv_buffer}
  222.               $88/$40/$FF/             {mov  [bx+si-1],al       ;copy char to recv_buffer}
  223.               $43/                     {inc  bx                 ;update buf_end}
  224.               $E8/$22/$00/             {call adj_idx}
  225.               $89/$1E/BUF_END/         {mov  [buf_end],bx}
  226.               $3B/$1E/BUF_START/       {cmp  bx, [buf_start]}
  227.               $75/$0C/                 {jnz  ISR_DONE}
  228.               $8B/$1E/BUF_START/       {mov  bx,buf_start}
  229.               $43/                     {inc  bx}
  230.               $E8/$10/$00/             {call adj_idx}
  231.               $89/$1E/BUF_START/       {mov  [buf_start],bx}
  232.               $BA/$20/$00/             {mov  dx,20H            ;EOI command for 8259A PIC}
  233.               $B0/$20/                 {mov  al,20H            ;EOI port for 8259A PIC}
  234.               $EE/                     {out  dx,al             ;End Of Interrupt}
  235.               $5E/                     {pop  si}
  236.               $5A/                     {pop  dx}
  237.               $5B/                     {pop  bx}
  238.               $58/                     {pop  ax}
  239.               $1F/                     {pop  ds}
  240.               $CF/                     {iret}
  241. {adj_idx:}    $2E/$8B/$16/*+11/        {mov  dx,[lcl_buf_len]}
  242.               $42/                     {inc  dx}
  243.               $39/$DA/                 {cmp  dx,bx}
  244.               $75/$03/                 {jnz  no_change}
  245.               $BB/$01/$00/             {mov  bx,1}
  246. {no_change:}  $C3/                     {ret}
  247. {lcl_buf_len;}$00/$00/                 {dw  0}
  248.               $00/$01/                 {dw  1}
  249. {exit:}       $90                      {nop}
  250.  );
  251.  port[IER] := ENABLE_DAV;              {interrupt enable}
  252.  a := port[MCR];
  253.  port[MCR] := a or ENABLE_OUT2;        {preserve RTS and enable OUT2}
  254.  a := port[IMR];
  255.  a := a and ENABLE_IRQ4;
  256.  port[IMR]  := a;
  257. end;
  258.  
  259.  
  260. procedure remove_port;
  261. {disables DAV, OUT2 and IRQ4 so that COM1: will no longer be serviced}
  262. var
  263.    a : byte;
  264. begin
  265.      a         := port[IMR];
  266.      port[IMR] := a or DISABLE_IRQ4;
  267.      port[IER] := DISABLE_DAV;
  268.      a         := port[MCR];
  269.      port[MCR] := a and DISABLE_OUT2;
  270. end;
  271.  
  272.  
  273. procedure break;
  274. {send a break}
  275. var a,b : byte;
  276. begin
  277.  a := port[LCR];
  278.  b := (a and $7F) or $40;
  279.  port[LCR] := b;
  280.  delay(400);
  281.  port[LCR] := a;
  282. end;
  283.  
  284. procedure setup;
  285. {initialize most stuff - you may want to replace this routine completely}
  286. begin
  287.  dbits        := 8;
  288.  parity       := none;
  289.  stop_bits    := 1;
  290.  speed        := DEFAULT_BAUD;
  291.  init_port;
  292.  term_ready(true);
  293. end;
  294.